package com.midea.thread;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @description：CAS操作可能会带来ABA问题的解决办法 AtomicStampedReference
 * 对比版本号，每次修改的时候要同步修改版本号
 * @author: wangwl23
 * @create: 2021-08-08 18:28
 */
public class CasABADemo2 {
    public static AtomicStampedReference<Integer> a = new AtomicStampedReference(new Integer(1), 1);

    public static void main(String[] args) {
        Thread main = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer expectReference = a.getReference();
                    Integer newReference = expectReference + 1;
                    int expectStamp = a.getStamp();
                    int newStamp = expectStamp + 1;
                    Thread.sleep(1000);//主线程休眠一秒钟，让出cpu
                    boolean isCasSuccess = a.compareAndSet(expectReference, newReference, expectStamp, newStamp);
                    System.out.println("操作线程" + Thread.currentThread().getName() + ".cas操作:" + isCasSuccess);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }, "主线程");

        Thread other = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(20);//确保主线程优先执行

                    a.compareAndSet(a.getReference(), a.getReference() + 1, a.getReference(), a.getStamp() + 1);//a +1,a=2
                    System.out.println("操作线程" + Thread.currentThread().getName() + "【increment】，值=" + a.getReference());
                    a.compareAndSet(a.getReference(), a.getReference() - 1, a.getReference(), a.getStamp() + 1);//a +1,a=2
                    System.out.println("操作线程" + Thread.currentThread().getName() + "【decrement】，值=" + a.getReference());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }, "干扰线程");

        main.start();
        other.start();
    }
}
